package com.ihk.toiletfinder;

import java.io.FileInputStream;

import org.json.JSONObject;

import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;
import android.widget.Toast;

import com.ihk.model.Parser;
import com.ihk.model.Toilet;
import com.ihk.model.UserLocation;
import com.mapquest.android.maps.DefaultItemizedOverlay;
import com.mapquest.android.maps.GeoPoint;
import com.mapquest.android.maps.ItemizedOverlay;
import com.mapquest.android.maps.MapActivity;
import com.mapquest.android.maps.MapView;
import com.mapquest.android.maps.MyLocationOverlay;
import com.mapquest.android.maps.Overlay;
import com.mapquest.android.maps.OverlayItem;
import com.mapquest.android.maps.RouteManager;
import com.mapquest.android.maps.RouteResponse;
import com.mapquest.android.maps.ServiceResponse.Info;

public class OpenStreetMapActivity extends MapActivity{

	private MapView map;
	private WebView itinerary;
	private RouteManager routeManager;
	private UserLocation location = UserLocation.getInstance();
	private SharedPreferences prefs;
	private MyLocationOverlay myLocationOverlay;
	
	private GeoPoint targetedToilet;
    
	/** If true, only the handicaped toilet are display. */
    boolean showHandicap;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_open_street_map);

		initMap();
		initRouteManager();
    	
    	if(Parser.getToilets() == null) {
			try {
				Parser.getInstance().parse(new FileInputStream(Parser.getFilePath()));
			} catch (Exception e) {
				e.printStackTrace();
			}
    	}

		if(location.isGpsEnable()){
	        myLocationOverlay = new MyLocationOverlay(this, map);
	        myLocationOverlay.enableMyLocation();
	        
	        myLocationOverlay.runOnFirstFix(new Runnable() {
	        	@Override
	        	public void run() {
	        		GeoPoint gp = myLocationOverlay.getMyLocation();
	        		map.getController().animateTo(gp);
	        		map.getOverlays().add(myLocationOverlay);
	        		
	        		location.setLatitude(gp.getLatitude());
	        		location.setLongitude(gp.getLongitude());
	        		
	        		if(targetedToilet == null)
	        			initDefaultTargetedToilet();
	        		
	        		addItinerary();
	        	}

	        });
		}
		
		addOverlay();
		
		if(!location.isGpsEnable()){
			initDefaultTargetedToilet();
			addItinerary();
		}
	}
	
	@Override
	protected void onResume() {
		if(location.isGpsEnable()){
			myLocationOverlay.enableMyLocation();
			myLocationOverlay.enableCompass();
		}
		super.onResume();
    }
	
	@Override
    protected void onPause() {
		super.onPause();
		if(location.isGpsEnable()){
			myLocationOverlay.disableCompass();
			myLocationOverlay.disableMyLocation();
		}
    }
	
	// return false since no route is being displayed
	@Override
	public boolean isRouteDisplayed() {
		return false;
	}
	
	private void initMap(){
		map = (MapView) findViewById(R.id.map);
		itinerary = (WebView) findViewById(R.id.itinerary);

		// set the zoom level, center point and enable the default zoom controls
		map.getController().setZoom(17);
		map.getController().setCenter(new GeoPoint(location.getLatitude(), location.getLongitude()));
		map.setBuiltInZoomControls(true);
	}
	
	private void initRouteManager(){
		routeManager = new RouteManager(this);
		routeManager.setMapView(map);
		routeManager.setItineraryView(itinerary);
		
		try{
			JSONObject options=new JSONObject();
			options.put("routeType","pedestrian");
			routeManager.setOptions(options.toString());
		}catch (Exception e) {
			e.printStackTrace();
		}
		
		routeManager.setRouteCallback(new RouteManager.RouteCallback() {
			@Override
			public void onError(RouteResponse routeResponse) {
				Info info=routeResponse.info;
				int statusCode=info.statusCode;

				StringBuilder message =new StringBuilder();
				message.append("Unable to create route.\n")
					.append("Error: ").append(statusCode).append("\n")
					.append("Message: ").append(info.messages);
				Toast.makeText(getApplicationContext(), message.toString(), Toast.LENGTH_LONG).show();
			}

			@Override
			public void onSuccess(RouteResponse routeResponse) {
			}
		});
	}

	private void addOverlay() {
		prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
		showHandicap = prefs.getBoolean("handicapped", false);
		
		Drawable drawable = this.getResources().getDrawable(R.drawable.pissoir);
		DefaultItemizedOverlay overlay = new DefaultItemizedOverlay(drawable);
		
		GeoPoint point;
		OverlayItem overlayItem;
		
		if(!location.isGpsEnable()){
			point = new GeoPoint(location.getLatitude(), location.getLongitude());
			overlayItem = new OverlayItem(point, "Current location", "");
			overlayItem.setMarker(Overlay.setAlignment(getResources()
					.getDrawable(R.drawable.blue_dot_circle),
					Overlay.CENTER_HORIZONTAL | Overlay.CENTER_VERTICAL));
			overlay.addItem(overlayItem);
		}

		for (Toilet toilet : Parser.getToilets()) {
			point = new GeoPoint(toilet.latitude, toilet.longitude);
			overlayItem = new OverlayItem(point, toilet.street + ", " + toilet.city, toilet.type);
		
			if (toilet.type.equals("Handicap")) {
				overlayItem.setMarker(Overlay.setAlignment(getResources()
						.getDrawable(R.drawable.handicap),
						Overlay.CENTER_HORIZONTAL | Overlay.CENTER_VERTICAL));
				overlay.addItem(overlayItem);
			} else if (toilet.type.equals("Pissoir")) {
				if(!showHandicap){
					overlayItem.setMarker(Overlay.setAlignment(getResources()
							.getDrawable(R.drawable.pissoir),
							Overlay.CENTER_HORIZONTAL | Overlay.CENTER_VERTICAL));
					overlay.addItem(overlayItem);
				}
			} else if (toilet.type.equals("Unisex")) {
				if(!showHandicap){
					overlayItem.setMarker(Overlay.setAlignment(getResources()
							.getDrawable(R.drawable.unisex),
							Overlay.CENTER_HORIZONTAL | Overlay.CENTER_VERTICAL));
					overlay.addItem(overlayItem);
				}
			} else
				System.out.println("Type of toilet unknown.");
		}

		map.getOverlays().add(overlay);
			
		// add a focus change listener
		overlay.setOnFocusChangeListener(new ItemizedOverlay.OnFocusChangeListener() {
			@SuppressWarnings("rawtypes")
			@Override
			public void onFocusChanged(ItemizedOverlay overlay, OverlayItem newFocus) {
				Toast.makeText(map.getContext().getApplicationContext(),
						newFocus.getTitle() + ": " + newFocus.getSnippet(),
						Toast.LENGTH_SHORT).show();
				
				targetedToilet = newFocus.getPoint();
				addItinerary();

			}
		});
	}
	
	private void initDefaultTargetedToilet(){
		targetedToilet = new GeoPoint(Parser.getToilets().get(0).latitude, Parser.getToilets().get(0).longitude);
		double distance = Math.pow(Parser.getToilets().get(0).latitude - location.getLatitude(), 2) + Math.pow(Parser.getToilets().get(0).longitude - location.getLongitude(),  2);;
		
		for(Toilet toilet : Parser.getToilets()){
			if(!showHandicap || (showHandicap && toilet.type.equals("Handicap"))){
				double distanceTmp = Math.pow(toilet.latitude - location.getLatitude(), 2) + Math.pow(toilet.longitude - location.getLongitude(),  2);
				if(distanceTmp < distance){
					targetedToilet = new GeoPoint(toilet.latitude, toilet.longitude);
					distance = distanceTmp;
				}
			}
		}
	}

	private void addItinerary(){
		this.runOnUiThread(new Runnable() {
			public void run() {
				routeManager.createRoute("{latLng:{lat:" + location.getLatitude() + ",lng:" + location.getLongitude() + "}}", "{latLng:{lat:" + targetedToilet.getLatitude() + ",lng:" + targetedToilet.getLongitude() + "}}");
			}
		});
	}

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	switch (item.getItemId()) {
    	case R.id.itemSettings:
    		startActivity(new Intent(this, SettingsActivity.class));
    		break;
    	case R.id.itemAddToilet:
    		startActivity(new Intent(this, AddToiletActivity.class));
    	break;
    	}
    	
    	return true;
    }
}